<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>10.7 Self-Consistency（自洽性） - Langchain框架教程</title>
    <link rel="stylesheet" href="../shared_styles.css">
</head>
<body>
    <div class="container">
        <h1> 第十章：AI系统提示词设计进阶</h1>
        <section id="s10-7">
            <h2>10.7 Self-Consistency（自洽性）</h2>
            <p>Self-Consistency（自洽性）是一种用于提高大型语言模型（LLM）在推理任务上表现的技术。它的核心思想是，对于同一个问题，通过多次采样生成不同的思维链（Chain-of-Thought），然后选择最一致（即出现频率最高）的最终答案作为最终输出。这可以看作是CoT Prompting的一种增强或后处理方法。</p>

            <h3>Self-Consistency 的原理</h3>
            <p>LLM在生成文本时具有一定的随机性（由温度参数控制）。对于一个需要推理的问题，即使使用相同的提示词，多次调用LLM也可能产生不同的思维过程和最终答案。Self-Consistency假设，正确的答案更有可能通过多种不同的推理路径得出，因此在多次采样结果中出现的频率会更高。</p>
            <p>通过生成多条思维链并进行“投票”，Self-Consistency可以有效地减少LLM在单次推理中可能出现的错误，提高最终答案的鲁棒性。</p>

            <h3>Self-Consistency 的实现步骤</h3>
            <p>实现 Self-Consistency 通常包括以下步骤：</p>
            <ol>
                <li><strong>生成提示词：</strong> 使用CoT Prompting（通常是Zero-shot CoT或Few-shot CoT）构建提示词，鼓励LLM生成思维链。</li>
                <li><strong>多次采样：</strong> 使用较高的温度参数（例如，0.5到1.0之间）多次调用LLM（例如，调用N次，N通常在10到100之间），为同一个问题生成N个不同的响应，每个响应都包含一个思维链和一个最终答案。</li>
                <li><strong>提取答案：</strong> 从每个响应中提取最终答案。这通常需要一个解析步骤，例如查找“最终答案是：”后面的文本。</li>
                <li><strong>投票：</strong> 统计所有提取到的最终答案的出现频率。</li>
                <li><strong>选择最一致的答案：</strong> 选择出现频率最高的答案作为最终输出。如果存在平局，可以随机选择其中一个，或者根据其他标准（如思维链的长度或复杂性）进行选择。</li>
            </ol>

            <h3>在Langchain中实现 Self-Consistency</h3>
            <p>Langchain本身并没有一个直接的<code>SelfConsistencyChain</code>或类似的组件，因为Self-Consistency更多是一种后处理策略。但我们可以通过结合Langchain的现有组件和一些自定义逻辑来实现它。</p>
            <p>以下是一个使用Langchain组件和Python代码实现Self-Consistency的示例框架：</p>

            <pre><code class="language-python">
# (接上一节的Qwen LLM初始化代码)
# from langchain_openai import ChatOpenAI
# from langchain_core.prompts import ChatPromptTemplate, SystemMessagePromptTemplate, HumanMessagePromptTemplate
# from langchain_core.output_parsers import StrOutputParser
# import os
#
# api_key = os.environ.get("DASHSCOPE_API_KEY")
# # 为了演示Self-Consistency，我们可能需要稍微提高温度以获得更多样的输出
# qwen_llm_consistent = ChatOpenAI(
#     base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
#     api_key=api_key,
#     model="qwen-plus",
#     temperature=0.7 # 提高温度以增加多样性
# )

from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from collections import Counter
import re # 用于提取答案

# 1. 生成提示词 (使用 Zero-shot CoT)
prompt_template_cot = ChatPromptTemplate.from_messages([
    HumanMessagePromptTemplate.from_template("请计算：{question}。让我们一步一步地思考。")
])

# 2. 定义一个函数来调用LLM并提取答案
def generate_and_extract_answer(chain, question):
    response = chain.invoke({"question": question})
    print(f"生成的响应:\n{response}\n---")
    # 尝试从响应中提取最终答案
    # 这里的正则表达式需要根据LLM的实际输出格式进行调整
    match = re.search(r"最终答案是[：:]\s*(.*)", response)
    if match:
        return match.group(1).strip()
    # 如果没有明确的“最终答案是”，尝试提取最后一个数字或结论
    # 这部分逻辑可能需要更复杂，取决于LLM的输出风格
    numbers = re.findall(r'\d+', response)
    if numbers:
         return numbers[-1] # 简单地取最后一个数字作为答案
    return None # 无法提取答案

# 3. 多次采样并收集答案
num_samples = 10 # 采样次数
question_to_solve = "(12 + 8) * 3 / 5"
answers = []

# 创建链
cot_chain = prompt_template_cot | qwen_llm_consistent | StrOutputParser()

print(f"对问题 '{question_to_solve}' 进行 {num_samples} 次采样...")
for _ in range(num_samples):
    answer = generate_and_extract_answer(cot_chain, question_to_solve)
    if answer:
        answers.append(answer)

print(f"\n收集到的答案列表: {answers}")

# 4. 投票并选择最一致的答案
if answers:
    answer_counts = Counter(answers)
    most_common_answer = answer_counts.most_common(1)[0][0]
    print(f"投票结果: {answer_counts}")
    print(f"最一致的答案: {most_common_answer}")
else:
    print("未能从采样结果中提取到任何答案。")

                    </code></pre>

            <h3>Self-Consistency 的优势和劣势</h3>
            <p><strong>优势：</strong></p>
            <ul>
                <li>显著提高复杂推理任务的准确性。</li>
                <li>通过集成多个推理路径的结果，增强了答案的鲁棒性。</li>
            </ul>
            <p><strong>劣势：</strong></p>
            <ul>
                <li>计算成本较高，需要多次调用LLM。</li>
                <li>需要额外的逻辑来解析LLM的输出并提取最终答案。</li>
                <li>对于不需要多步推理的简单任务，效果不明显。</li>
            </ul>

            <h3>总结</h3>
            <p>Self-Consistency是一种通过生成多条思维链并进行投票来提高LLM推理准确性的技术。虽然它增加了计算开销，但对于需要高精度推理的应用场景（如数学问题、复杂逻辑问答等）来说，Self-Consistency是一个非常有效的策略。在Langchain中，可以通过组合提示词、LLM调用和自定义后处理逻辑来实现Self-Consistency。</p>
        </section>

        <div class="navigation">
            <a href="../langchain_tutorial_outline.html">返回教程目录</a>
            <a href="../chapter10/chapter10_6_chain_of_thought.html">&larr; 上一节：10.6 Chain-of-Thought Prompting（思维链提示）</a>
            <a href="../chapter10/chapter10_8_retrieval_augmented_generation.html">下一节：10.8 Retrieval Augmented Generation (RAG)（检索增强生成） &rarr;</a>
        </div>
    </div>
</body>
</html>
